<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>hovertreewelcome</title>
    <meta name="keywords" content="hovertreewelcome">
</head>

<body>
    <style type="text/css">
    * {margin: 0; padding: 0; outline: none; box-sizing: border-box; min-width: 0; }
    svg {display: block; }
    a:link, a:hover, a:active, a:visited {text-decoration: none; }
    .loadbox {background: #282c34; position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 999999; display: flex; align-items: center; justify-content: center;
    }
    .loadbox .outbox {display: flex; justify-content: center; flex-direction: column; position: absolute; left: 50%; transform: translateX(-50%); top: 0; width: 100%; height: 100%; color: #fff; z-index: 999; align-items: center; }
    .loadbox .txt {display: flex; justify-content: center; font-size: 2.25rem; font-weight: 100; width: 100%; color: #fff; z-index: 999; align-items: center; }
    .loadbox .txt span {margin: 0 1rem; }
    .l_morebtn {position: relative; z-index: 1; margin-top: 3.75rem; display: inline-block; }
    .l_morebtn::before {content: ""; position: absolute; width: 100%; height: 100%; z-index: -1; box-sizing: border-box; left: 0; top: 0; border: 3px solid #dcdddf; transition: .5s; border-radius: 2.5rem; }
    .l_morebtn a {display: flex; align-items: center; justify-content: center; position: absolute; width: 100%; height: 100%; left: 0; top: 0; font-size: 1rem; color: #5d5e60; }
    .l_morebtn svg path {fill: none; box-sizing: border-box; stroke-width: 3; stroke: #0150ce; stroke-dasharray: 44, 152; stroke-dashoffset: 57; transition: all .3s linear 0s; }
    .l_morebtn:hover svg path {stroke-dasharray: 200, 0; stroke-dashoffset: 140; }
    .l_morebtn.white a {color: #fff; }
    .l_morebtn.white:before {border-color: rgba(255, 255, 255, .4); }
    .l_morebtn.white svg path {stroke: #fff; }
    .l_morebtn:hover:before {opacity: 0; }
    .l_morebtn.blue:before {border-color: #e0eafa; }
    #hovertreecontainer {position: absolute; left: 0; top: 0; width: 100%; height: 100%; }
    #canvas {position: absolute; left: 0; top: 0; width: 100%; height: 100%; }
    </style>
    <div class="loadbox">
        <div class="outbox">
            <div class="txt">
                <span>官</span>
                <span>网</span>
                <span>建</span>
                <span>设</span>
                <span>中</span>
                <span>.</span>
                <span>.</span>
                <span>.</span>
            </div>
            <div class="btnbox" aos="fade-up" aos-duration="1000" aos-delay="3100">
                <div class="l_morebtn white" id="load_btn">
                    <svg viewbox="0 0 174.5 54.5" width="174.5px" height="54.5px">
                        <path fill-rule="evenodd" stroke="rgb(220, 221, 223)" stroke-width="3px" stroke-linecap="butt" stroke-linejoin="miter" fill="none" d="M25.500,1.500 L147.500,1.500 C160.755,1.500 171.500,12.245 171.500,25.500 L171.500,27.500 C171.500,40.755 160.755,51.500 147.500,51.500 L25.500,51.500 C12.245,51.500 1.500,40.755 1.500,27.500 L1.500,25.500 C1.500,12.245 12.245,1.500 25.500,1.500 Z" />
                    </svg>
                    <a href='#'>账号注册</a>
                </div>
            </div>
        </div>
        <div id="hovertreecontainer">
            <canvas id="canvas"></canvas>
        </div>
    </div>
    <script type="text/javascript" src="./hovertreewelcome.js"></script>
    <script type="text/javascript">
    (function(window) {
        var ctx,
            hue,
            form,
            buffer,
            target = {},
            tendrils = [],
            settings = {};

        settings.debug = true;
        settings.friction = 0.5;
        settings.trails = 20;
        settings.size = 50;
        settings.dampening = 0.25;
        settings.tension = 0.98;

        Math.TWO_PI = Math.PI * 2;

        // ========================================================================================
        function Oscillator(options) {
            this.init(options || {});
        }
        Oscillator.prototype = (function() {
            var value = 0;
            return {
                init: function(options) {
                    this.phase = options.phase || 0;
                    this.offset = options.offset || 0;
                    this.frequency = options.frequency || 0.001;
                    this.amplitude = options.amplitude || 1;
                },
                update: function() {
                    this.phase += this.frequency;
                    value = this.offset + Math.sin(this.phase) * this.amplitude;
                    return value;
                },
                value: function() {
                    return value;
                }
            };
        })();

        // ========================================================================================
        // Tendril hovertree.com
        // ----------------------------------------------------------------------------------------
        function Tendril(options) {
            this.init(options || {});
        }
        Tendril.prototype = (function() {
            function Node() {
                this.x = 0;
                this.y = 0;
                this.vy = 0;
                this.vx = 0;
            }
            return {
                init: function(options) {
                    this.spring = options.spring + (Math.random() * 0.1) - 0.05;
                    this.friction = settings.friction + (Math.random() * 0.01) - 0.005;
                    this.nodes = [];
                    for (var i = 0, node; i < settings.size; i++) {
                        node = new Node();
                        node.x = target.x;
                        node.y = target.y;
                        this.nodes.push(node);
                    }
                },
                update: function() {
                    var spring = this.spring,
                        node = this.nodes[0];
                    node.vx += (target.x - node.x) * spring;
                    node.vy += (target.y - node.y) * spring;
                    for (var prev, i = 0, n = this.nodes.length; i < n; i++) {
                        node = this.nodes[i];
                        if (i > 0) {
                            prev = this.nodes[i - 1];
                            node.vx += (prev.x - node.x) * spring;
                            node.vy += (prev.y - node.y) * spring;
                            node.vx += prev.vx * settings.dampening;
                            node.vy += prev.vy * settings.dampening;
                        }
                        node.vx *= this.friction;
                        node.vy *= this.friction;
                        node.x += node.vx;
                        node.y += node.vy;
                        spring *= settings.tension;
                    }
                },

                draw: function() {
                    var x = this.nodes[0].x,
                        y = this.nodes[0].y,
                        a, b;
                    ctx.beginPath();
                    ctx.moveTo(x, y);
                    for (var i = 1, n = this.nodes.length - 2; i < n; i++) {
                        a = this.nodes[i];
                        b = this.nodes[i + 1];
                        x = (a.x + b.x) * 0.5;
                        y = (a.y + b.y) * 0.5;
                        ctx.quadraticCurveTo(a.x, a.y, x, y);
                    }
                    a = this.nodes[i];
                    b = this.nodes[i + 1];
                    ctx.quadraticCurveTo(a.x, a.y, b.x, b.y);
                    ctx.stroke();
                    ctx.closePath();
                }
            };
        })();

        // ----------------------------------------------------------------------------------------
        function init(event) {
            document.removeEventListener('mousemove', init);
            document.removeEventListener('touchstart', init);
            document.addEventListener('mousemove', mousemove);
            document.addEventListener('touchmove', mousemove);
            document.addEventListener('touchstart', touchstart);
            mousemove(event);
            reset();
            loop();
        }
        function reset() {
            tendrils = [];
            for (var i = 0; i < settings.trails; i++) {
                tendrils.push(new Tendril({
                    spring: 0.45 + 0.025 * (i / settings.trails)
                }));
            }
        }
        function loop() {
            if (!ctx.running) return;
            ctx.globalCompositeOperation = 'source-over';
            ctx.fillStyle = 'rgba(8,5,16,0.4)';
            ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
            ctx.globalCompositeOperation = 'lighter';
            // ctx.strokeStyle = 'hsla(' + Math.round(hue.update()) + ',90%,50%,0.25)';
            ctx.strokeStyle = 'rgba(1,80,206,.25)';
            ctx.lineWidth = 1;
            if (ctx.frame % 60 == 0) {
                console.log(hue.update(), Math.round(hue.update()), hue.phase, hue.offset, hue.frequency, hue.amplitude);
            }
            for (var i = 0, tendril; i < settings.trails; i++) {
                tendril = tendrils[i];
                tendril.update();
                tendril.draw();
            }
            ctx.frame++;
            ctx.stats.update();
            requestAnimFrame(loop);
        }
        function resize() {
            ctx.canvas.width = window.innerWidth;
            ctx.canvas.height = window.innerHeight;
        }
        function start() {
            if (!ctx.running) {
                ctx.running = true;
                loop();
            }
        }
        function stop() {
            ctx.running = false;
        }
        function mousemove(event) {
            if (event.touches) {
                target.x = event.touches[0].pageX;
                target.y = event.touches[0].pageY;
            } else {
                target.x = event.clientX
                target.y = event.clientY;
            }
            event.preventDefault();
        }
        function touchstart(event) {
            if (event.touches.length == 1) {
                target.x = event.touches[0].pageX;
                target.y = event.touches[0].pageY;
            }
        }
        function keyup(event) {
            switch (event.keyCode) {
                case 32:
                    save();
                    break;
                default:
                    // console.log(event.keyCode); hovertree.com
            }
        }
        function save() {
            if (!buffer) {
                buffer = document.createElement('canvas');
                buffer.width = screen.availWidth;
                buffer.height = screen.availHeight;
                buffer.ctx = buffer.getContext('2d');
                form = document.createElement('form');
                form.method = 'post';
                form.input = document.createElement('input');
                form.input.type = 'hidden';
                form.input.name = 'data';
                form.appendChild(form.input);
                document.body.appendChild(form);
            }
            buffer.ctx.fillStyle = 'rgba(1,80,206,.25)';
            buffer.ctx.fillRect(0, 0, buffer.width, buffer.height);
            buffer.ctx.drawImage(canvas,
                Math.round(buffer.width / 2 - canvas.width / 2),
                Math.round(buffer.height / 2 - canvas.height / 2)
            );
            window.open(buffer.toDataURL(), 'wallpaper', 'top=0,left=0,width=' + buffer.width + ',height=' + buffer.height);
        }
        window.requestAnimFrame = (function() {
            return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(fn) { window.setTimeout(fn, 1000 / 60) };
        })();
        window.onload = function() {
            ctx = document.getElementById('canvas').getContext('2d');
            ctx.stats = new Stats();
            ctx.running = true;
            ctx.frame = 1;
            hue = new Oscillator({
                phase: Math.random() * Math.TWO_PI,
                amplitude: 85,
                frequency: 0.0015,
                offset: 285
            });
            document.addEventListener('mousemove', init);
            document.addEventListener('touchstart', init);
            document.body.addEventListener('orientationchange', resize);
            window.addEventListener('resize', resize);
            window.addEventListener('keyup', keyup);
            window.addEventListener('focus', start);
            window.addEventListener('blur', stop);
            resize();
            if (window.DEBUG) {
                var gui = new dat.GUI();
                // gui.add(settings, 'debug');
                settings.gui.add(settings, 'trails', 1, 30).onChange(reset);
                settings.gui.add(settings, 'size', 25, 75).onFinishChange(reset);
                settings.gui.add(settings, 'friction', 0.45, 0.55).onFinishChange(reset);
                settings.gui.add(settings, 'dampening', 0.01, 0.4).onFinishChange(reset);
                settings.gui.add(settings, 'tension', 0.95, 0.999).onFinishChange(reset);
                document.body.appendChild(ctx.stats.domElement);
            }
        };
    })(window);
    </script>
</body>

</html>